home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / src / gdb-4.12 / bfd / doc / chew.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-03  |  22.5 KB  |  1,376 lines

  1. /* chew
  2.    Copyright (C) 1990-1991 Free Software Foundation, Inc.
  3.    Contributed by steve chamberlain @cygnus
  4.  
  5. This file is part of BFD, the Binary File Descriptor library.
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /*
  22.  Yet another way of extracting documentation from source.
  23.  No, I haven't finished it yet, but I hope you people like it better
  24.  that the old way
  25.   
  26.  sac
  27.  
  28. Basically, this is a sort of string forth, maybe we should call it
  29. struth?
  30.  
  31. You define new words thus:
  32. : <newword> <oldwords> ;
  33. There is  no
  34.  
  35. */
  36.  
  37.  
  38.  
  39. #include <ansidecl.h>
  40. #include "sysdep.h"
  41.  
  42. #define DEF_SIZE 5000
  43. #define STACK 50
  44.  
  45. int internal_wanted;
  46. int internal_mode;
  47.  
  48. int warning;
  49.  
  50.  
  51. /* Here is a string type ... */
  52.  
  53. typedef struct buffer 
  54. {
  55.     char *ptr;
  56.     unsigned int write_idx;
  57.     unsigned int size;
  58. } string_type;
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66. static void DEFUN(init_string_with_size,(buffer, size),
  67.        string_type *buffer AND
  68.        unsigned int size )
  69. {
  70.     buffer->write_idx = 0;
  71.     buffer->size = size;
  72.     buffer->ptr = malloc(size);
  73. }
  74.  
  75. static void DEFUN(init_string,(buffer),
  76.        string_type *buffer)
  77. {
  78.     init_string_with_size(buffer, DEF_SIZE);
  79.  
  80. }
  81.  
  82. static int DEFUN(find, (str, what),
  83.       string_type *str AND
  84.       char *what)
  85. {
  86.     unsigned int i;
  87.     char *p;
  88.     p = what;
  89.     for (i = 0; i < str->write_idx && *p; i++) 
  90.     {
  91.     if (*p == str->ptr[i])
  92.      p++;
  93.     else
  94.      p = what;
  95.     }
  96.     return (*p == 0);
  97.     
  98. }
  99.  
  100. static void DEFUN(write_buffer,(buffer),
  101.        string_type *buffer)
  102. {
  103.     fwrite(buffer->ptr, buffer->write_idx, 1, stdout);
  104. }
  105.  
  106.  
  107. static void DEFUN(delete_string,(buffer),
  108.        string_type *buffer)
  109. {
  110.     free(buffer->ptr);
  111. }
  112.  
  113.  
  114. static char *DEFUN(addr, (buffer, idx),
  115.         string_type *buffer AND
  116.         unsigned int idx)
  117. {
  118.     return buffer->ptr + idx;
  119. }
  120.  
  121. static char DEFUN(at,(buffer, pos),
  122.        string_type *buffer AND
  123.        unsigned int pos) 
  124. {
  125.     if ( pos >= buffer->write_idx) 
  126.     {
  127.     return 0;
  128.     }
  129.     return buffer->ptr[pos];
  130. }
  131.  
  132. static void DEFUN(catchar,(buffer, ch), 
  133.        string_type *buffer AND
  134.        char ch)
  135. {
  136.     if (buffer->write_idx == buffer->size) 
  137.     {
  138.     buffer->size *=2;
  139.     buffer->ptr = realloc(buffer->ptr, buffer->size);
  140.     }
  141.  
  142.     buffer->ptr[buffer->write_idx ++ ] = ch;
  143. }
  144.  
  145.  
  146. static void DEFUN(overwrite_string,(dst,   src),
  147.        string_type *dst AND
  148.        string_type *src)
  149. {
  150.     free(dst->ptr);
  151.     dst->size = src->size;
  152.     dst->write_idx = src->write_idx;
  153.     dst->ptr = src->ptr;
  154. }
  155.  
  156. static void DEFUN(catstr,(dst, src),
  157.        string_type *dst AND
  158.        string_type *src)
  159. {
  160.     unsigned int i;
  161.     for (i = 0; i < src->write_idx; i++) 
  162.     {
  163.     catchar(dst, src->ptr[i]);
  164.     }
  165. }
  166.  
  167.  
  168. static void DEFUN(cattext,(buffer, string),
  169.        string_type *buffer AND
  170.        char *string)
  171. {
  172.     
  173.     while (*string) 
  174.     {
  175.     catchar(buffer, *string);
  176.     string++;
  177.     }
  178. }
  179.  
  180. static void DEFUN(catbuf,(buffer, buf, len),
  181.        string_type *buffer AND
  182.        char *buf AND
  183.        unsigned int len)
  184. {
  185.     
  186.     while (len--) 
  187.     {
  188.     catchar(buffer, *buf);
  189.     buf++;
  190.     }
  191. }
  192.  
  193.  
  194.  
  195. static unsigned int 
  196. DEFUN(skip_white_and_stars,(src, idx),
  197.       string_type *src AND
  198.       unsigned int idx)
  199. {
  200.     while (isspace(at(src,idx)) 
  201.        || (at(src,idx) == '*' && at(src,idx +1) !='/'
  202.            && at(src,idx -1) != '\n')) 
  203.      idx++;
  204.     return idx;
  205.     
  206.  
  207. }
  208. /***********************************************************************/
  209.  
  210.  
  211. string_type stack[STACK];
  212. string_type *tos;
  213.  
  214. unsigned int idx = 0; /* Pos in input buffer */
  215. string_type *ptr; /* and the buffer */
  216. typedef void (*stinst_type)();
  217. stinst_type *pc;
  218. stinst_type sstack[STACK];
  219. stinst_type *ssp = &sstack[0];
  220. int istack[STACK];
  221. int *isp = &istack[0];
  222.  
  223. typedef int *word_type;
  224.  
  225.  
  226.  
  227. struct dict_struct
  228. {
  229.     char *word;
  230.     struct dict_struct *next;
  231.    stinst_type *code;
  232.     int code_length;
  233.     int code_end;
  234.     int var;
  235.     
  236. };
  237. typedef struct dict_struct dict_type;
  238. #define WORD(x) static void x()
  239.  
  240. static void DEFUN(exec,(word),
  241.           dict_type *word)
  242. {
  243.     pc = word->code;
  244.     while (*pc) 
  245.     {
  246.     (*pc)();
  247.     }
  248.     
  249. }
  250. WORD(call)
  251. {
  252. stinst_type *oldpc = pc;
  253.     dict_type *e;
  254.     e =  (dict_type *)(pc [1]);
  255.     exec(e);
  256.     pc = oldpc + 2;
  257.     
  258. }
  259.  
  260. WORD(remchar)
  261. {
  262.     tos->write_idx--;    
  263.     pc++;
  264.     
  265. }
  266.  
  267. WORD(push_number)
  268. {
  269.     isp++;
  270.     pc++;
  271.     *isp = (int)(*pc);
  272.     pc++;
  273.     
  274. }
  275.  
  276.  
  277.  
  278.  
  279. WORD(push_text)
  280. {
  281.     
  282.     tos++;
  283.     init_string(tos);
  284.     pc++;
  285.     cattext(tos,*((char **)pc));
  286.     pc++;
  287.     
  288. }
  289.  
  290.  
  291.    
  292. /* This function removes everything not inside comments starting on
  293.    the first char of the line from the  string, also when copying
  294.    comments, removes blank space and leading *'s 
  295.    Blank lines are turned into one blank line
  296.  */
  297.  
  298. static void 
  299. DEFUN(remove_noncomments,(src,dst),
  300.        string_type *src AND
  301.        string_type *dst)
  302. {
  303.     unsigned int idx = 0;
  304.     
  305.     while (at(src,idx)) 
  306.     {
  307.     /* Now see if we have a comment at the start of the line */
  308.     if (at(src,idx) == '\n' 
  309.         && at(src,idx+1) ==  '/' 
  310.         && at(src,idx+2) == '*') 
  311.     {
  312.         idx+=3;
  313.         
  314.         idx = skip_white_and_stars(src,idx);
  315.  
  316.         /* Remove leading dot */
  317.         if (at(src, idx) == '.')
  318.          idx++;
  319.         
  320.         /* Copy to the end of the line, or till the end of the
  321.            comment */
  322.         while (at(src, idx))
  323.         {
  324.         if (at(src, idx) == '\n') 
  325.         {
  326.             /* end of line, echo and scrape of leading blanks  */
  327.             if (at(src,idx +1) == '\n')
  328.              catchar(dst,'\n');
  329.             catchar(dst,'\n');
  330.             idx++;
  331.             idx =   skip_white_and_stars(src, idx);
  332.         }
  333.         else if (at(src, idx) == '*' && at(src,idx+1) == '/') 
  334.         {
  335.             idx +=2 ;
  336.             cattext(dst,"\nENDDD\n");
  337.             break;
  338.         }
  339.         else 
  340.         {
  341.             catchar(dst, at(src, idx));
  342.             idx++;
  343.         }
  344.         }
  345.     }
  346.     else idx++;
  347.     }
  348. }
  349.  
  350. /* turn:
  351.      foobar name(stuff);
  352.    into:
  353.      foobar
  354.      name PARAMS ((stuff));
  355.    and a blank line.
  356.  */
  357.  
  358. static void
  359. DEFUN_VOID(paramstuff)
  360. {
  361.     unsigned int openp;
  362.     unsigned int fname;
  363.     unsigned int idx;
  364.     string_type out;
  365.     init_string(&out);
  366.     
  367.  
  368.     /* make sure that it's not already param'd or proto'd */
  369.     if(find(tos,"PARAMS") || find(tos,"PROTO") || !find(tos,"(")) {
  370.         catstr(&out,tos);
  371.     }
  372.     else 
  373.     {
  374.     /* Find the open paren */
  375.     for (openp = 0; at(tos, openp) != '('  && at(tos,openp); openp++)
  376.      ;
  377.  
  378.     fname = openp;
  379.     /* Step back to the fname */
  380.     fname--;
  381.     while (fname && isspace(at(tos, fname)))
  382.      fname --;
  383.     while (fname && !isspace(at(tos,fname)) && at(tos,fname) != '*')
  384.      fname--;
  385.  
  386.     fname++;
  387.     
  388.     for (idx = 0; idx < fname; idx++)     /* Output type */
  389.     {
  390.         catchar(&out, at(tos,idx));
  391.     }
  392.     
  393.         cattext(&out, "\n");    /* Insert a newline between type and fnname */
  394.  
  395.     for (idx = fname; idx < openp; idx++)         /* Output fnname */
  396.     {
  397.         catchar(&out, at(tos,idx));
  398.     }
  399.  
  400.     cattext(&out," PARAMS (");
  401.  
  402.     while (at(tos,idx) && at(tos,idx) !=';') 
  403.     {
  404.         catchar(&out, at(tos, idx));
  405.         idx++;
  406.     }
  407.     cattext(&out,");\n\n");
  408.     }
  409.     overwrite_string(tos, &out);    
  410.     pc++;
  411.     
  412. }
  413.  
  414.  
  415.  
  416. /* turn {*
  417.    and *} into comments */
  418.  
  419. WORD(translatecomments)
  420. {
  421.     unsigned int idx = 0;
  422.     string_type out;
  423.     init_string(&out);
  424.     
  425.     while (at(tos, idx)) 
  426.     {
  427.     if (at(tos,idx) == '{' && at(tos,idx+1) =='*') 
  428.     {
  429.         cattext(&out,"    /*");
  430.         idx+=2;
  431.     }
  432.     else if (at(tos,idx) == '*' && at(tos,idx+1) =='}') 
  433.     {
  434.         cattext(&out,"*/");
  435.         idx+=2;
  436.     }
  437.     else  
  438.     {
  439.         catchar(&out, at(tos, idx));
  440.         idx++;
  441.     }
  442.     }
  443.  
  444.  
  445.     overwrite_string(tos, &out);
  446.     
  447.     pc++;
  448.     
  449. }
  450.  
  451. /* turn everything not starting with a . into a comment */
  452.  
  453. WORD(manglecomments)
  454. {
  455.     unsigned int idx = 0;
  456.     string_type out;
  457.     init_string(&out);
  458.     
  459.     while (at(tos, idx)) 
  460.     {
  461.     if (at(tos,idx) == '\n' && at(tos,idx+1) =='*') 
  462.     {
  463.         cattext(&out,"    /*");
  464.         idx+=2;
  465.     }
  466.     else if (at(tos,idx) == '*' && at(tos,idx+1) =='}') 
  467.     {
  468.         cattext(&out,"*/");
  469.         idx+=2;
  470.     }
  471.     else  
  472.     {
  473.         catchar(&out, at(tos, idx));
  474.         idx++;
  475.     }
  476.     }
  477.  
  478.  
  479.     overwrite_string(tos, &out);
  480.     
  481.     pc++;
  482.     
  483. }
  484.  
  485. /* Mod tos so that only lines with leading dots remain */
  486. static void
  487. DEFUN_VOID(outputdots)
  488. {
  489.     unsigned int idx = 0;
  490.     string_type out;
  491.     init_string(&out);
  492.     
  493.     while (at(tos, idx)) 
  494.     {
  495.     if (at(tos, idx) == '\n' && at(tos, idx+1) == '.') 
  496.     {
  497.         idx += 2;
  498.         
  499.         while (at(tos, idx) && at(tos, idx)!='\n')
  500.         {
  501.         if (at(tos,idx) == '{' && at(tos,idx+1) =='*') 
  502.         {
  503.             cattext(&out," /*");
  504.             idx+=2;
  505.         }
  506.         else if (at(tos,idx) == '*' && at(tos,idx+1) =='}') 
  507.         {
  508.             cattext(&out,"*/");
  509.             idx+=2;
  510.         }
  511.         else  
  512.         {
  513.             catchar(&out, at(tos, idx));
  514.             idx++;
  515.         }
  516.         }
  517.         catchar(&out,'\n');
  518.     }
  519.     else 
  520.     {
  521.         idx++;
  522.     }
  523.     }    
  524.  
  525.     overwrite_string(tos, &out);
  526.     pc++;
  527.     
  528. }
  529.  
  530. /* Find lines starting with . and | and put example around them on tos */
  531. WORD(courierize)
  532. {
  533.     string_type out;
  534.     unsigned int idx = 0;
  535.     int command = 0;
  536.     
  537.     init_string(&out);
  538.     
  539.     while (at(tos, idx)) 
  540.     {
  541.     if (at(tos, idx) == '\n' 
  542.         && (at(tos, idx +1 ) == '.'
  543.         || at(tos,idx+1) == '|')) 
  544.     {
  545.         cattext(&out,"\n@example\n");
  546.         do 
  547.         {
  548.         idx += 2;
  549.         
  550.         while (at(tos, idx) && at(tos, idx)!='\n')
  551.         {
  552.             if (at(tos,idx)=='{' && at(tos,idx+1) =='*') 
  553.             {
  554.             cattext(&out," /*");
  555.             idx+=2;
  556.             }
  557.             else if (at(tos,idx)=='*' && at(tos,idx+1) =='}') 
  558.             {
  559.             cattext(&out,"*/");
  560.             idx+=2;
  561.             }
  562.                 else if (at(tos,idx) == '{' && !command)
  563.             {
  564.             cattext(&out,"@{");
  565.             idx++;
  566.             }
  567.                 else if (at(tos,idx) == '}' && !command)
  568.             {
  569.             cattext(&out,"@}");
  570.             idx++;
  571.             }
  572.             else 
  573.             {
  574.             if (at(tos,idx) == '@')
  575.                 command = 1;
  576.             else if (isspace(at(tos,idx)) || at(tos,idx) == '}')
  577.                 command = 0;
  578.             catchar(&out, at(tos, idx));
  579.             idx++;
  580.             }
  581.             
  582.         }
  583.         catchar(&out,'\n');
  584.         }  
  585.         while (at(tos, idx) == '\n' 
  586.            && (at(tos, idx+1) == '.')
  587.            || (at(tos,idx+1) == '|'));
  588.         cattext(&out,"@end example");
  589.     }
  590.     else 
  591.     {    
  592.         catchar(&out, at(tos, idx));
  593.         idx++;
  594.     }
  595.     }    
  596.  
  597.     overwrite_string(tos, &out);
  598.     pc++;
  599.  
  600.     
  601. }
  602.  
  603. /* Finds any lines starting with "o ", if there are any, then turns
  604.    on @itemize @bullet, and @items each of them. Then ends with @end
  605.    itemize, inplace at TOS*/
  606.  
  607.  
  608. WORD(bulletize)
  609. {
  610.     unsigned int idx = 0;
  611.     int on = 0;
  612.     string_type out;
  613.     init_string(&out);
  614.     
  615.     while (at(tos, idx)) {
  616.     if (at(tos, idx) == '@' &&
  617.         at(tos, idx+1) == '*') 
  618.     {
  619.       cattext(&out,"*");
  620.       idx+=2;
  621.     }
  622.     
  623. else
  624.         if (at(tos, idx) == '\n' &&
  625.         at(tos, idx+1) == 'o' &&
  626.         isspace(at(tos, idx +2)))
  627.         {
  628.         if (!on) 
  629.         {
  630.             cattext(&out,"\n@itemize @bullet\n");
  631.             on = 1;
  632.             
  633.         }
  634.         cattext(&out,"\n@item\n");
  635.         idx+=3;
  636.         }
  637.         else 
  638.         {
  639.         catchar(&out, at(tos, idx));
  640.         if (on && at(tos, idx) == '\n' &&
  641.             at(tos, idx+1) == '\n' &&
  642.             at(tos, idx+2) != 'o')
  643.         {
  644.             cattext(&out, "@end itemize");
  645.             on = 0;
  646.         }
  647.         idx++;
  648.         
  649.         }
  650.     }
  651.     if (on) 
  652.     {
  653.     cattext(&out,"@end itemize\n");
  654.     }    
  655.  
  656.     delete_string(tos);
  657.     *tos = out;
  658.     pc++;
  659.     
  660. }
  661.  
  662. /* Turn <<foo>> into @code{foo} in place at TOS*/
  663.    
  664.  
  665. WORD(do_fancy_stuff)
  666. {
  667.     unsigned int idx = 0;
  668.     string_type out;
  669.     init_string(&out);
  670.     while (at(tos, idx)) 
  671.     {
  672.     if (at(tos, idx) == '<' 
  673.         && at(tos, idx+1) == '<'
  674.         && !isspace(at(tos,idx + 2))) 
  675.     {
  676.         /* This qualifies as a << startup */
  677.         idx +=2;
  678.         cattext(&out,"@code{");
  679.         while(at(tos,idx) &&
  680.           at(tos,idx) != '>' )
  681.         {
  682.         catchar(&out, at(tos, idx));
  683.         idx++;
  684.         
  685.         }
  686.         cattext(&out,"}");
  687.         idx+=2;
  688.     }
  689.     else 
  690.     {
  691.         catchar(&out, at(tos, idx));
  692.         idx++;
  693.     }
  694.     }
  695.     delete_string(tos);
  696.     *tos = out;
  697.     pc++;
  698.     
  699. }
  700. /* A command is all upper case,and alone on a line */
  701. static int 
  702. DEFUN( iscommand,(ptr, idx),
  703.       string_type *ptr AND
  704.       unsigned int idx)
  705. {
  706.     unsigned int len = 0;
  707.     while (at(ptr,idx)) {
  708.         if (isupper(at(ptr,idx)) || at(ptr,idx) == ' ' ||
  709.         at(ptr,idx) == '_') 
  710.         {
  711.          len++;
  712.          idx++;
  713.      }
  714.         else if(at(ptr,idx) == '\n')
  715.         {
  716.         if (len >4) return 1;
  717.         return 0;
  718.         }
  719.         else return 0;
  720.     }
  721.     return 0;
  722.  
  723. }
  724.  
  725.  
  726. DEFUN(copy_past_newline,(ptr, idx, dst),
  727.       string_type *ptr AND
  728.       unsigned int idx AND
  729.       string_type *dst)
  730. {
  731.     while (at(ptr, idx) && at(ptr, idx) != '\n') 
  732.     {
  733.     catchar(dst, at(ptr, idx));
  734.     idx++;
  735.     
  736.     }    
  737.     catchar(dst, at(ptr, idx));
  738.     idx++;
  739.     return idx;
  740.  
  741. }
  742.  
  743. WORD(icopy_past_newline)
  744. {
  745.     tos++;
  746.     init_string(tos);
  747.     idx = copy_past_newline(ptr, idx, tos);
  748.     pc++;    
  749. }
  750.  
  751. /* indent
  752.    Take the string at the top of the stack, do some prettying */
  753.  
  754.  
  755.  
  756.  
  757. WORD(kill_bogus_lines)
  758. {
  759.     int sl ;
  760.     
  761.     int nl = 0;
  762.     int idx = 0;
  763.     int c;
  764.     int dot = 0    ;
  765.     
  766.     string_type out;    
  767.     init_string(&out);
  768.     /* Drop leading nl */
  769.     while (at(tos,idx) == '\n')
  770.     {
  771.     idx++;
  772.     }
  773.     c = idx;
  774.     
  775.     /* Find the last char */
  776.     while (at(tos,idx))
  777.     {
  778.     idx++;
  779.     }
  780.     
  781.     /* find the last non white before the nl */
  782.     idx--;
  783.     
  784.     while (idx && isspace(at(tos,idx)))
  785.      idx--;
  786.     idx++;
  787.     
  788.     /* Copy buffer upto last char, but blank lines before and after
  789.        dots don't count */
  790.     sl = 1;
  791.  
  792.     while (c < idx)
  793.     {
  794.     if (at(tos,c) == '\n' 
  795.         && at(tos,c+1) == '\n'
  796.         && at(tos,c+2) == '.') 
  797.     {
  798.         /* Ignore two newlines before a dot*/
  799.         c++;
  800.     }
  801.     else if (at(tos,c) == '.' && sl)
  802.     {
  803.         /* remember that this line started with a dot */
  804.         dot=2;
  805.     }
  806.     else if (at(tos,c) == '\n' 
  807.          && at(tos,c+1) == '\n'
  808.          && dot)
  809.     {
  810.         c++;
  811.         /* Ignore two newlines when last line was dot */
  812.     }
  813.  
  814.     catchar(&out, at(tos,c));
  815.     if (at(tos,c) == '\n')
  816.     {
  817.         sl = 1;
  818.         
  819.         if (dot == 2)dot=1;else dot = 0;
  820.     }
  821.     
  822.     c++;    
  823.  
  824.     }
  825.     
  826.     /* Append nl*/
  827.     catchar(&out, '\n');
  828.     pc++;
  829.     delete_string(tos);
  830.     *tos = out;
  831.     
  832.     
  833. }
  834.  
  835. WORD(indent)
  836. {
  837.     string_type out;
  838.     int tab = 0;
  839.     int idx = 0;
  840.     int ol =0;
  841.     init_string(&out);
  842.     while (at(tos,idx)) {
  843.         switch (at(tos,idx)) 
  844.         {
  845.           case '\n':
  846.         cattext(&out,"\n");
  847.         idx++;
  848.         if (tab) 
  849.         {
  850.             cattext(&out,"    ");
  851.         }
  852.         ol = 0;
  853.         break;
  854.           case '(':
  855.         tab++;
  856.         if (ol == 0)
  857.             cattext(&out,"   ");
  858.         idx++;
  859.         cattext(&out,"(");
  860.         ol = 1;
  861.         break;
  862.           case ')':
  863.         tab--;
  864.         cattext(&out,")");
  865.         idx++;
  866.         ol=1;
  867.         
  868.         break;
  869.           default:
  870.         catchar(&out,at(tos,idx));
  871.         ol=1;
  872.         
  873.         idx++;
  874.         break;
  875.         }
  876.     }    
  877.  
  878.     pc++;
  879.     delete_string(tos);
  880.     *tos = out;
  881.  
  882. }
  883.  
  884.  
  885. WORD(get_stuff_in_command)
  886. {
  887.     tos++;
  888.     init_string(tos);
  889.  
  890.     while (at(ptr, idx)) {
  891.         if (iscommand(ptr, idx))  break;
  892.         idx =   copy_past_newline(ptr, idx, tos);
  893.     }
  894. pc++;    
  895. }
  896.  
  897. WORD(swap)
  898. {
  899.     string_type t;
  900.     
  901.     t = tos[0];
  902.     tos[0] = tos[-1];
  903.     tos[-1] =t; 
  904.     pc++;
  905.     
  906. }
  907.  
  908. WORD(other_dup)
  909. {
  910.     tos++;
  911.     init_string(tos);
  912.     catstr(tos, tos-1);
  913.     pc++;
  914.     
  915. }
  916.  
  917.  
  918.  
  919. WORD(icatstr)
  920. {
  921.     catstr(tos-1, tos);
  922.     delete_string(tos);
  923.     tos--;
  924.     pc++;
  925.     
  926. }
  927.  
  928. WORD(skip_past_newline)
  929. {
  930.     while (at(ptr,idx) 
  931.        && at(ptr,idx) != '\n')
  932.      idx++;
  933.     idx++;
  934.     pc++;
  935. }
  936.  
  937.  
  938. WORD(internalmode)
  939. {
  940.     internal_mode = *(isp);
  941.     isp--;
  942.     pc++;
  943. }
  944.  
  945. WORD(maybecatstr)
  946. {
  947.     if (internal_wanted == internal_mode) 
  948.     {
  949.     catstr(tos-1, tos);
  950.     }
  951.     delete_string(tos);
  952.     tos--;
  953.     pc++;
  954.     
  955. }
  956.  
  957. char *
  958. DEFUN(nextword,(string, word),
  959.       char *string AND
  960.       char **word)
  961. {
  962.     char *word_start;
  963.     int idx;
  964.     char *dst;
  965.     char *src;
  966.     
  967.     int length = 0;
  968.     
  969.     while (isspace(*string) || *string == '-') {
  970.         if (*string == '-') 
  971.         {
  972.         while (*string && *string != '\n') 
  973.          string++;
  974.         
  975.         }
  976.         else {
  977.             string++;
  978.         }
  979.     }
  980.     if (!*string) return 0;
  981.     
  982.     word_start = string;        
  983.     if (*string == '"') 
  984.     {
  985.     string++;
  986.     length++;
  987.     
  988.     while (*string != '"') 
  989.     {
  990.         string++;
  991.         length++;
  992.     }
  993.     }
  994.     else     
  995.     {
  996.     
  997.  
  998.     while (!isspace(*string)) 
  999.     {
  1000.         string++;
  1001.         length++;
  1002.     
  1003.     }
  1004.     }
  1005.     
  1006.     *word = malloc(length + 1);
  1007.  
  1008.     dst = *word;
  1009.     src = word_start;
  1010.  
  1011.  
  1012.     for (idx= 0; idx < length; idx++) 
  1013.     {
  1014.     
  1015.     if (src[idx] == '\\' && src[idx+1] == 'n') 
  1016.     {
  1017.         *dst++ = '\n';
  1018.         idx++;
  1019.     
  1020.     }
  1021.     else *dst++ = src[idx];
  1022.     }
  1023.     *dst++ = 0;
  1024.  
  1025.  
  1026.  
  1027.  
  1028.  
  1029.     if(*string)    
  1030.      return string + 1;
  1031.     else 
  1032.      return 0;
  1033.     
  1034. }
  1035. dict_type *root;
  1036. dict_type *
  1037. DEFUN(lookup_word,(word),
  1038.       char *word)
  1039. {
  1040.   dict_type *ptr = root;
  1041.   while (ptr) {
  1042.       if (strcmp(ptr->word, word) == 0) return ptr;
  1043.       ptr = ptr->next;
  1044.         
  1045.     }
  1046.   if (warning)
  1047.    fprintf(stderr,"Can't find %s\n",word);
  1048.   return 0;
  1049.     
  1050.     
  1051. }
  1052.  
  1053. static void DEFUN_VOID(perform)
  1054. {
  1055.   tos = stack;
  1056.     
  1057.   while (at(ptr, idx)) {
  1058.       /* It's worth looking through the command list */
  1059.       if (iscommand(ptr, idx))
  1060.       {
  1061.     unsigned int i;
  1062.     int found = 0;
  1063.  
  1064.     char *next;
  1065.     dict_type *word ;
  1066.         
  1067.     (void)        nextword(addr(ptr, idx), &next);
  1068.  
  1069.  
  1070.     word = lookup_word(next);
  1071.  
  1072.  
  1073.         
  1074.  
  1075.     if (word) 
  1076.     {
  1077.       exec(word);
  1078.     }
  1079.     else
  1080.     {
  1081.       if (warning)
  1082.        fprintf(stderr,"warning, %s is not recognised\n",  next);
  1083.       skip_past_newline();
  1084.     }
  1085.         
  1086.       }
  1087.       else skip_past_newline();
  1088.  
  1089.     }
  1090. }
  1091.  
  1092. dict_type *
  1093. DEFUN(newentry,(word),
  1094.       char *word)
  1095. {
  1096.     dict_type *new = (dict_type *)malloc(sizeof(dict_type));
  1097.     new->word = word;
  1098.     new->next = root;
  1099.     root = new;
  1100.     new->code = (stinst_type *)malloc(sizeof(stinst_type ));
  1101.     new->code_length = 1;
  1102.     new->code_end = 0;
  1103.     return new;
  1104.     
  1105. }
  1106.  
  1107.  
  1108. unsigned int
  1109. DEFUN(add_to_definition,(entry, word), 
  1110.       dict_type *entry AND
  1111.       stinst_type word)
  1112. {
  1113.     if (entry->code_end == entry->code_length) 
  1114.     {
  1115.     entry->code_length += 2;
  1116.     entry->code =
  1117.      (stinst_type *) realloc((char *)(entry->code),
  1118.                    entry->code_length *sizeof(word_type));
  1119.     }
  1120.     entry->code[entry->code_end] = word;
  1121.     
  1122. return     entry->code_end++;  
  1123. }
  1124.  
  1125.  
  1126.  
  1127.  
  1128.  
  1129.  
  1130.  
  1131. void
  1132. DEFUN(add_intrinsic,(name, func),
  1133.       char *name AND
  1134.       void (*func)())
  1135. {
  1136.     dict_type *new = newentry(name);
  1137.     add_to_definition(new, func);
  1138.     add_to_definition(new, 0);
  1139. }
  1140.  
  1141. WORD(push_addr)
  1142. {
  1143.     
  1144.  
  1145. }
  1146.  
  1147. void
  1148. DEFUN(add_var,(name),
  1149.       char *name)
  1150. {
  1151.     dict_type *new = newentry(name);
  1152.     add_to_definition(new, push_number);
  1153.     add_to_definition(new, (stinst_type)(&(new->var)));
  1154.     add_to_definition(new,0);
  1155.     
  1156. }
  1157.       
  1158.  
  1159.  
  1160.  
  1161. void 
  1162. DEFUN(compile, (string), 
  1163.       char *string)
  1164.  
  1165. {
  1166.     int jstack[STACK];
  1167.     int *jptr = jstack;
  1168.     /* add words to the dictionary */
  1169.     char *word;
  1170.     string = nextword(string, &word);
  1171.     while (string && *string && word[0]) 
  1172.     {
  1173.     if (strcmp(word,"var")==0) 
  1174.     {
  1175.  string=nextword(string, &word);
  1176.       
  1177.       add_var(word);
  1178.  string=nextword(string, &word);
  1179.     }
  1180. else    
  1181.         
  1182.     if (word[0] == ':')
  1183.     {
  1184.         dict_type *ptr;
  1185.         /* Compile a word and add to dictionary */
  1186.         string = nextword(string, &word);
  1187.         
  1188.         ptr = newentry(word);
  1189.         string = nextword(string, &word);
  1190.         while (word[0] != ';' ) 
  1191.         {
  1192.          switch (word[0]) 
  1193.          {
  1194.             
  1195.             
  1196.            case '"':
  1197.              /* got a string, embed magic push string
  1198.             function */
  1199.              add_to_definition(ptr, push_text);
  1200.              add_to_definition(ptr, (stinst_type)(word+1));
  1201.              break;
  1202.            case '0':
  1203.            case '1':
  1204.            case '2':
  1205.            case '3':
  1206.            case '4':
  1207.            case '5':
  1208.            case '6':
  1209.            case '7':
  1210.            case '8':
  1211.            case '9':
  1212.              /* Got a number, embedd the magic push number
  1213.             function */
  1214.              add_to_definition(ptr, push_number);
  1215.              add_to_definition(ptr, (stinst_type)atol(word));
  1216.              break;
  1217.            default:
  1218.              add_to_definition(ptr, call);
  1219.              add_to_definition(ptr, (stinst_type)lookup_word(word));
  1220.          }
  1221.  
  1222.         string = nextword(string, &word);             
  1223.         }
  1224.         add_to_definition(ptr,0);
  1225.         string = nextword(string, &word);
  1226.     }
  1227.     else 
  1228.     {
  1229.         fprintf(stderr,"syntax error at %s\n",string-1);
  1230.     }        
  1231.     }
  1232.  
  1233. }
  1234.  
  1235.  
  1236. static void DEFUN_VOID(bang)
  1237. {
  1238. *(int *)((isp[0])) = isp[-1];
  1239. isp-=2;
  1240. pc++;
  1241.  
  1242. }
  1243.  
  1244. WORD(atsign)
  1245. {
  1246.     isp[0] = *(int *)(isp[0]);
  1247.     pc++;
  1248. }
  1249.  
  1250. WORD(hello)
  1251. {
  1252.     
  1253.     printf("hello\n");
  1254.     pc++;    
  1255. }
  1256.  
  1257.  
  1258.  
  1259. static void DEFUN(read_in, (str, file), 
  1260.        string_type *str AND
  1261.           FILE *file)
  1262. {
  1263.     char buff[10000];    
  1264.     unsigned int r;
  1265.     do 
  1266.     {
  1267.     r = fread(buff, 1, sizeof(buff), file);
  1268.     catbuf(str, buff, r);
  1269.     }
  1270.     while (r);
  1271.     buff[0] = 0;
  1272.     
  1273.     catbuf(str, buff,1);
  1274.     
  1275. }
  1276.  
  1277.  
  1278. static void DEFUN_VOID(usage)
  1279. {
  1280.     fprintf(stderr,"usage: -[d|i|g] <file >file\n");
  1281.     exit(33);    
  1282. }
  1283.  
  1284. /* There is no reliable way to declare exit.  Sometimes it returns
  1285.    int, and sometimes it returns void.  Sometimes it changes between
  1286.    OS releases.  Trying to get it declared correctly in the hosts file
  1287.    is a pointless waste of time.  */
  1288.  
  1289. static void
  1290. chew_exit ()
  1291. {
  1292.   exit (0);
  1293. }
  1294.  
  1295. int DEFUN(main,(ac,av),
  1296. int ac AND
  1297. char *av[])
  1298. {
  1299.   unsigned int i;
  1300.   string_type buffer;
  1301.   string_type pptr;
  1302.  
  1303.   init_string(&buffer);
  1304.   init_string(&pptr);
  1305.   init_string(stack+0);
  1306.   tos=stack+1;
  1307.   ptr = &pptr;
  1308.     
  1309.   add_intrinsic("push_text", push_text);
  1310.   add_intrinsic("!", bang);
  1311.   add_intrinsic("@", atsign);
  1312.   add_intrinsic("hello",hello);    
  1313.   add_intrinsic("skip_past_newline", skip_past_newline );
  1314.   add_intrinsic("catstr", icatstr );
  1315.   add_intrinsic("copy_past_newline", icopy_past_newline );
  1316.   add_intrinsic("dup", other_dup );
  1317.   add_intrinsic("remchar", remchar );
  1318.   add_intrinsic("get_stuff_in_command", get_stuff_in_command );
  1319.   add_intrinsic("do_fancy_stuff", do_fancy_stuff );
  1320.   add_intrinsic("bulletize", bulletize );
  1321.   add_intrinsic("courierize", courierize );
  1322.   /* If the following line gives an error, exit() is not declared in the
  1323.      ../hosts/foo.h file for this host.  Fix it there, not here!  */
  1324.   /* No, don't fix it anywhere; see comment on chew_exit--Ian Taylor.  */
  1325.   add_intrinsic("exit", chew_exit );
  1326.   add_intrinsic("swap", swap );
  1327.   add_intrinsic("outputdots", outputdots );
  1328.   add_intrinsic("paramstuff", paramstuff );
  1329.   add_intrinsic("maybecatstr", maybecatstr );
  1330.   add_intrinsic("translatecomments", translatecomments );
  1331.   add_intrinsic("kill_bogus_lines", kill_bogus_lines);
  1332.   add_intrinsic("indent", indent);
  1333.   add_intrinsic("internalmode", internalmode);
  1334.     
  1335.   /* Put a nl at the start */
  1336.   catchar(&buffer,'\n');
  1337.  
  1338.   read_in(&buffer, stdin); 
  1339.   remove_noncomments(&buffer, ptr);
  1340.   for (i= 1; i < ac; i++) 
  1341.   {
  1342.     if (av[i][0] == '-')
  1343.     {
  1344.       if (av[i][1] == 'f')
  1345.       {
  1346.     string_type b;
  1347.     FILE *f;
  1348.     init_string(&b);
  1349.  
  1350.     f  = fopen(av[i+1],"r");
  1351.     if (!f) 
  1352.     {
  1353.       fprintf(stderr,"Can't open the input file %s\n",av[i+1]);
  1354.       return 33;
  1355.     }
  1356.         
  1357.           
  1358.     read_in(&b, f);
  1359.     compile(b.ptr);
  1360.     perform();    
  1361.       }
  1362.       else if (av[i][1] == 'i') 
  1363.       {
  1364.     internal_wanted = 1;
  1365.       }
  1366.       else if (av[i][1] == 'w') 
  1367.       {
  1368.     warning = 1;
  1369.       }
  1370.     }
  1371.  
  1372.   }      
  1373.   write_buffer(stack+0);
  1374.   return 0;
  1375. }
  1376.